{/* Copyright 2020 Adobe. All rights reserved.
This file is licensed to you under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. You may obtain a copy
of the License at http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software distributed under
the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
OF ANY KIND, either express or implied. See the License for the specific language
governing permissions and limitations under the License. */}

import {Layout} from '@react-spectrum/docs';
export default Layout;

import docs from 'docs:@react-aria/breadcrumbs';
import {HeaderInfo, FunctionAPI, TypeContext, InterfaceType, PageDescription} from '@react-spectrum/docs';
import {Keyboard} from '@react-spectrum/text';
import packageData from '@react-aria/breadcrumbs/package.json';
import Anatomy from './anatomy.svg';

---
category: Navigation
keywords: [breadcrumbs, aria]
---

# useBreadcrumbs

<PageDescription>{docs.exports.useBreadcrumbs.description}</PageDescription>

<HeaderInfo
  packageData={packageData}
  componentNames={['useBreadcrumbs', 'useBreadcrumbItem']}
  sourceData={[
    {type: 'W3C', url: 'https://www.w3.org/WAI/ARIA/apg/patterns/breadcrumb/'}
  ]} />

## API

<FunctionAPI function={docs.exports.useBreadcrumbs} links={docs.links} />
<FunctionAPI function={docs.exports.useBreadcrumbItem} links={docs.links} />

## Features

Breadcrumbs provide a list of links to parent pages of the current page in hierarchical order.
`useBreadcrumbs` and `useBreadcrumbItem` help implement these in an accessible way.

* Support for mouse, touch, and keyboard interactions on breadcrumbs
* Support for navigation links via `<a>` elements or custom element types via ARIA
* Localized ARIA labeling support for landmark navigation region
* Support for disabled breadcrumbs

## Anatomy

<Anatomy />

Breadcrumbs consist of a navigation landmark element and a list of links, typically with a visual separator
icon between each item. The last link represents the current page in the hierarchy, with the previous links representing the
parent pages of the current page. Each of these parent links can be clicked, tapped, or
triggered via the <Keyboard>Enter</Keyboard> key to navigate to that page.

`useBreadcrumbs` returns props to be spread onto the navigation element:

<TypeContext.Provider value={docs.links}>
  <InterfaceType properties={docs.links[docs.exports.useBreadcrumbs.return.id].properties} />
</TypeContext.Provider>

`useBreadcrumbItem` returns props to spread onto the individual breadcrumb links:

<TypeContext.Provider value={docs.links}>
  <InterfaceType properties={docs.links[docs.exports.useBreadcrumbItem.return.id].properties} />
</TypeContext.Provider>

## Example

This example displays a basic list of breadcrumbs using an HTML
[&lt;nav&gt;](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/nav)
element, and a [&lt;ol&gt;](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/ol)
for the list of links. Each link is a span because we are handling the interactions
locally via `onPress`. `useBreadcrumbItem` automatically handles exposing these
spans as links to assistive technology.

The chevrons between each link are rendered using a span with `aria-hidden="true"` so that
screen readers do not pick them up. You could also render them similarly using SVG icons,
CSS `:after`, or other techniques.

The last link is non-interactive since it represents the current page. This is
passed to the last breadcrumb item by cloning the element and adding the `isCurrent`
prop.

```tsx example
import {useBreadcrumbs, useBreadcrumbItem} from '@react-aria/breadcrumbs';

function Breadcrumbs(props) {
  let {navProps} = useBreadcrumbs(props);
  let childCount = React.Children.count(props.children);

  return (
    <nav {...navProps}>
      <ol style={{display: 'flex', listStyle: 'none', margin: 0, padding: 0}}>
        {React.Children.map(props.children, (child, i) =>
          React.cloneElement(child, {isCurrent: i === childCount - 1})
        )}
      </ol>
    </nav>
  )
}

function BreadcrumbItem(props) {
  let ref = React.useRef(null);
  let {itemProps} = useBreadcrumbItem({...props, elementType: 'span'}, ref);
  return (
    <li>
      <span
        {...itemProps}
        ref={ref}
        style={{
          color: props.isDisabled ? 'var(--gray)' : 'var(--blue)',
          textDecoration: props.isCurrent || props.isDisabled ? 'none' : 'underline',
          fontWeight: props.isCurrent ? 'bold' : null,
          cursor: props.isCurrent || props.isDisabled ? 'default' : 'pointer'
        }}>
        {props.children}
      </span>
      {!props.isCurrent &&
        <span aria-hidden="true" style={{padding: '0 5px'}}>{'›'}</span>
      }
    </li>
  );
}

<Breadcrumbs>
  <BreadcrumbItem onPress={() => alert('Pressed Folder 1')}>Folder 1</BreadcrumbItem>
  <BreadcrumbItem onPress={() => alert('Pressed Folder 2')}>Folder 2</BreadcrumbItem>
  <BreadcrumbItem>Folder 3</BreadcrumbItem>
</Breadcrumbs>
```

## Navigation links

To render breadcrumbs that navigate to other pages rather than handle events via `onPress`, use an `<a>` element
for each BreadcrumbItem. This is the default `elementType`, so the option can be omitted from `useBreadcrumbItem`.

```tsx example export=true
///- begin collapse -///
function Breadcrumbs(props) {
  let {navProps} = useBreadcrumbs(props);
  let childCount = React.Children.count(props.children);

  return (
    <nav {...navProps}>
      <ol style={{display: 'flex', listStyle: 'none', margin: 0, padding: 0}}>
        {React.Children.map(props.children, (child, i) =>
          React.cloneElement(child, {isCurrent: i === childCount - 1})
        )}
      </ol>
    </nav>
  );
}
///- end collapse -///
function BreadcrumbItem(props) {
  let ref = React.useRef(null);
  let {itemProps} = useBreadcrumbItem(props, ref);
  return (
    <li>
      <a
        {...itemProps}
        ref={ref}
        href={props.href}
        style={{
          color: props.isDisabled ? 'var(--gray)' : 'var(--blue)',
          textDecoration: props.isCurrent || props.isDisabled ? 'none' : 'underline',
          fontWeight: props.isCurrent ? 'bold' : null,
          cursor: props.isCurrent || props.isDisabled ? 'default' : 'pointer'
        }}>
        {props.children}
      </a>
      {!props.isCurrent &&
        <span aria-hidden="true" style={{padding: '0 5px'}}>{'›'}</span>
      }
    </li>
  );
}

<Breadcrumbs>
  <BreadcrumbItem href="#">Home</BreadcrumbItem>
  <BreadcrumbItem href="#">React Aria</BreadcrumbItem>
  <BreadcrumbItem>useBreadcrumbs</BreadcrumbItem>
</Breadcrumbs>
```

## Usage

The following examples show how to use the `Breadcrumbs` component created in the above examples.

### Disabled

Breadcrumbs can be disabled using the `isDisabled` prop, passed to each disabled BreadcrumbItem. This indicates that navigation is not currently available. When a breadcrumb is disabled, `onPress` will not be triggered, navigation will not occur, and links will be marked as `aria-disabled` for assistive technologies.

```tsx example
<Breadcrumbs>
  <BreadcrumbItem href="#" isDisabled>Home</BreadcrumbItem>
  <BreadcrumbItem href="#">React Aria</BreadcrumbItem>
  <BreadcrumbItem>useBreadcrumbs</BreadcrumbItem>
</Breadcrumbs>
```
